package org.yray.sip.rtp.data;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReentrantLock;

@Slf4j
public class MediaChunk {
    private int chunkNum;
    private MediaChunk pre;
    private MediaChunk next;
    private MediaChunk pos;
    private byte[][] data;
    private ReentrantLock createMediaChunkLock;

    public int getChunkNum() {
        return chunkNum;
    }

    public void setChunkNum(int chunkNum) {
        this.chunkNum = chunkNum;
    }

    public static final int CHUNK_SIZE=1000;

    public MediaChunk getPos() {
        return pos;
    }

    public void setPos(MediaChunk pos) {
        this.pos = pos;
    }

    /***
     * 默认第0块
     */
    public MediaChunk()
    {
        this.chunkNum=0;
        this.data = new byte[CHUNK_SIZE][];
        this.pos=this;
        createMediaChunkLock=new ReentrantLock();
    }

    public void addData(int index,byte[] bs)
    {
        int tempcChunkNum=index/CHUNK_SIZE;
        int tempIndex=index%CHUNK_SIZE;
        MediaChunk curr=pos;
        //
        while (curr.chunkNum>tempcChunkNum)
        {
            if(curr.pre==null) {
                break;
            }
            curr=curr.pre;
        }
        while (curr.chunkNum<tempcChunkNum)
        {
            curr=createOrGetNextMediaChunk(curr);
        }
        if(curr.chunkNum==tempcChunkNum)
        {
            curr.addChunkData(tempIndex,bs);
        }
        else
        {
            log.error("there is a bug please check ,tempcChunkNum={},tempIndex={},index={},chunkNum={}"
                    ,tempcChunkNum,tempIndex,index,curr.chunkNum);
        }
    }

    private void addChunkData(int index,byte[] bs)
    {
        this.data[index]=bs;
    }

    private MediaChunk createOrGetNextMediaChunk(MediaChunk mediaChunk)
    {
        try {
            createMediaChunkLock.lock();
            if (mediaChunk.next == null) {
                MediaChunk tempNext = new MediaChunk();
                tempNext.chunkNum = mediaChunk.chunkNum + 1;
                mediaChunk.next = tempNext;
                tempNext.pre = mediaChunk;
            }
        }finally {
            createMediaChunkLock.unlock();
        }
        return mediaChunk.next;
    }


    public boolean hasNext()
    {
        return next!=null;
    }

    public MediaChunk getPre() {
        return pre;
    }

    public void setPre(MediaChunk pre) {
        this.pre = pre;
    }

    public MediaChunk getNext() {
        return next;
    }

    public void setNext(MediaChunk next) {
        this.next = next;
    }

    public byte[][] getData() {
        return data;
    }

    public void setData(byte[][] data) {
        this.data = data;
    }
}
